大家好!歡迎來到鐵人賽第八天。
昨天,我們探討了 Windows 環境下的 Python 虛擬環境(Virtual Environment)設定,成功解決套件依賴問題,讓 FastAPI 能夠獨立運行。
現在,我們的 API 已經可以在 0.0.0.0:8000 監聽請求,準備接收外部傳來的資料。
不過,當我們開始思考如何將 Wazuh 與後端程式串接時,才發現一個問題:
如果每隔幾分鐘就讓後端主動詢問 Wazuh「有沒有新的告警?」,不僅會產生額外的網路請求,也可能無法滿足即時通報的需求。
這種定期向伺服器查詢資料的方式稱為 Polling(輪詢)。
例如,假設我們每隔 60 秒查詢一次,即使系統沒有任何新告警,後端仍然會持續發送請求;而如果告警剛好發生在兩次查詢之間,就必須等待下一次輪詢才有機會取得資料。
因此,今天我們決定改用另一種設計方式:事件驅動(Event-driven)架構。
我們希望當 Wazuh 偵測到符合條件的安全事件時,就能主動將告警推送到 Python 後端,讓 FastAPI 第一時間接收資料。
聽起來似乎很簡單,但真正開始實作後,才發現 Docker 網路、Wazuh 設定檔與自訂整合腳本,才是今天最需要克服的挑戰。
在開始修改設定之前,我們必須先釐清整個系統的網路拓樸。
目前的架構如下:
整體資料流可以簡化為:
Ubuntu 測試主機
↓
Wazuh Agent
↓
Wazuh Manager(Docker)
↓
HTTP POST
↓
FastAPI(Windows)
↓
接收並處理告警
這裡最重要的問題是:
Wazuh 在 Docker 容器內執行,而 FastAPI 卻在 Windows 本機,兩者並不一定能直接透過 localhost 相互連線。
在網路通訊中,localhost 通常代表目前程式所在的網路環境。
當我們在 Windows 上執行 FastAPI 時,localhost:8000 指向 Windows 本機。
但如果 Wazuh 運行在 Docker 容器內,容器中的 localhost 就是容器本身,而不是 Windows 宿主機。
因此,即使 FastAPI 已經正常運行,Wazuh 也不一定能透過 localhost:8000 找到它。
這也是 Docker 網路環境中非常容易遇到的問題。
一開始,我們嘗試直接使用 Windows 本機的 IPv4 位址,讓 Wazuh 將告警傳送到 FastAPI。
但實際測試時,卻遇到了連線失敗的問題。
這讓我們開始檢查兩個可能的原因:
第一個問題:Windows 防火牆。
即使 FastAPI 已經啟動,如果 Windows 防火牆沒有允許外部連線進入 TCP 8000 Port,請求仍然可能被阻擋。
第二個問題:Docker 網路與宿主機之間的連線。
Docker 使用自己的虛擬網路環境,容器與宿主機之間的通訊需要經過適當的網路設定。
因此,不能只因為知道 Windows 的 IP 位址,就認為容器一定能順利連線。
經過檢查後,我們改用 Docker Desktop 提供的特殊主機名稱:
host.docker.internal
這個名稱可以讓 Docker 容器在支援的環境中,透過預先設定的網路路徑連接到宿主機。
因此,我們將原本的目標網址改成:
http://host.docker.internal:8000/webhook/wazuh
接著,再確認 Windows 防火牆允許必要的 TCP 8000 連線。
需要注意的是,host.docker.internal 並不是所有 Docker 環境都能直接使用的通用網址,實際上仍需確認 Docker 平台與網路設定。
完成這些調整後,我們終於解決了 Wazuh 容器與 Windows 本機之間的連線問題。
但這只是第一關,接下來還需要讓 Wazuh 知道什麼時候應該發送告警。
接下來,我們要讓 Wazuh 在符合條件時,自動將告警資料傳送到 FastAPI。
在 Wazuh 中,可以透過 ossec.conf 設定整合功能,讓 Manager 將符合條件的告警交給指定的整合程式處理。
我們進入 Wazuh Dashboard,依照目前使用的版本與部署方式,找到 Manager 的設定檔。
在 <ossec_config> 區塊內加入以下設定:
<integration>
<name>custom-webhook</name>
<hook_url>http://host.docker.internal:8000/webhook/wazuh</hook_url>
<level>3</level>
<alert_format>json</alert_format>
</integration>
這段設定的主要目的,是指定整合程式、接收告警的網址,以及需要處理的告警條件。
1. name
<name>custom-webhook</name>
指定整合程式的名稱。
這裡使用自訂的 custom-webhook,代表我們需要自行準備對應的整合腳本。
需要特別注意,Wazuh 不會因為設定了這個名稱,就自動產生一個可以使用的 Webhook 程式。
2. hook_url
<hook_url>http://host.docker.internal:8000/webhook/wazuh</hook_url>
指定接收告警的 API 網址。
當整合程式執行時,就會將資料傳送到這個位置。
3. level
<level>3</level>
設定告警等級的觸發門檻。
Wazuh 的告警等級通常介於 0 至 15,這裡設定為 3,代表希望納入等級 3 以上的告警。
不過,實際觸發情況仍會受到整合設定、告警規則與其他條件影響。
4. alert_format
<alert_format>json</alert_format>
指定告警資料的輸出格式為 JSON。
JSON 是一種常見的結構化資料格式,能讓後端程式更容易讀取告警中的欄位,例如事件時間、主機資訊與規則編號。
完成設定後,我們還需要確保對應的整合程式確實存在,否則 Wazuh 仍然無法完成資料傳送。
原本以為設定好 XML、重新啟動 Manager,就能順利收到告警。
沒想到查看 Wazuh 的日誌時,卻發現了類似以下的錯誤:
File not found inside 'integrations'
這個錯誤讓我們意識到:
Wazuh 的設定檔只負責告訴系統要執行哪個整合程式,但我們指定的 custom-webhook 並不存在於容器中。
也就是說,光有設定還不夠,我們還需要自行建立負責發送 HTTP 請求的腳本。
首先,我們透過 Docker 指令進入 Manager 容器。
docker exec -it single-node-wazuh.manager-1 bash
這裡的容器名稱需要依照自己的 Docker 環境調整。
進入容器後,前往 Wazuh 的整合程式目錄:
cd /var/ossec/integrations/
這個目錄存放 Wazuh 使用的整合程式。
接下來,我們需要建立自訂的 custom-webhook 腳本,讓 Wazuh 能夠將告警資料傳送到 FastAPI。
Wazuh 的整合程式會接收告警相關的參數,其中通常包含告警 JSON 檔案的位置。
自訂腳本的工作流程可以簡化為:
Wazuh 產生告警
↓
整合程式取得告警檔案
↓
讀取 JSON 資料
↓
透過 HTTP POST 發送
↓
FastAPI 接收資料
在這個過程中,腳本需要正確讀取 Wazuh 提供的告警檔案,再將資料送往指定的 API。
因此,腳本必須依照 Wazuh 整合程式的參數規範撰寫,而不是單純將任意檔案路徑當成固定值使用。
建立腳本後,我們還需要設定適當的檔案權限。
這次使用的指令如下:
chmod 750 custom-webhook
chmod 750 代表:
接著,設定檔案的擁有者與群組:
chown root:wazuh custom-webhook
這代表將檔案擁有者設為 root,群組設為 wazuh。
這些權限設定是為了符合 Wazuh 對整合程式的安全要求,避免因為檔案權限不符合預期而遭到拒絕執行。
完成腳本與權限設定後,我們再重新檢查設定檔與服務狀態,確認整合程式可以正常運作。
經過前面的網路設定、XML 配置與腳本除錯,我們終於來到最期待的測試階段。
這次,我們決定不再被動等待系統產生告警,而是親自在 Ubuntu 測試主機上觸發一個安全事件。
我們在 Ubuntu 終端機中,嘗試切換到不存在的使用者:
su - fakeuser
接著輸入錯誤密碼,讓系統產生登入失敗事件。
在符合對應規則與告警條件的情況下,Wazuh 就能偵測到這類異常登入行為,並產生相關告警。
這次測試的目的,是確認從 Ubuntu 到 Wazuh,再到 FastAPI 的整條資料傳輸流程是否正常。
完成測試後,我們立刻切回 Windows 的 VS Code 終端機。
成功的話會出現:
🔔 叮咚!收到一筆來自 Webhook 的資料!
INFO: 127.0.0.1:62284 - "POST /webhook/wazuh HTTP/1.1" 200 OK
這代表 FastAPI 已經成功接收到 HTTP POST 請求,並且正常回應了這次請求。
從 Ubuntu 觸發事件、Wazuh 偵測告警,到 Docker 容器將資料傳送給 Windows 上的 FastAPI,整個流程終於成功串接起來。
不過,200 OK 只能證明這次 HTTP 請求成功完成,後續仍需要確認收到的 JSON 是否完整,以及資料欄位是否符合預期。
今天,我們成功將 Wazuh 與 FastAPI 串接起來,讓系統具備主動推送安全告警的能力。
回顧今天遇到的問題與解決方式:
| 遇到的問題 | 解決方向 |
|---|---|
| Docker 容器無法直接連接 Windows 本機 | 使用 host.docker.internal 並檢查網路設定 |
| Windows 防火牆阻擋連線 | 確認 TCP 8000 的必要連線規則 |
| Wazuh 找不到自訂整合程式 | 建立 custom-webhook 腳本 |
| 腳本無法正常執行 | 檢查檔案權限與擁有者 |
| 不確定資料是否成功送達 | 透過 Ubuntu 觸發事件並觀察 FastAPI 日誌 |
今天最大的收穫,不只是讓系統成功收到一筆告警,更是理解了不同服務之間的網路通訊、Wazuh 整合機制,以及自訂腳本在整個架構中的角色。
我們的系統也從原本的被動監控,逐步發展成具備即時通報能力的自動化資安架構。
今天,我們已經成功讓 Wazuh 將告警資料推送到 FastAPI。
但目前後端收到的,還是一整包 JSON 資料。
這些資料可能包含大量欄位,如果沒有經過整理,就很難直接拿來進行後續分析。
因此,明天我們將進一步拆解這包 JSON Payload,學習如何從告警資料中萃取重要資訊,例如:
我們希望讓後端不只是收到資料,而是能夠真正理解告警的內容,為後續的漏洞驗證與自動化通報做好準備。
從今天的「成功收到告警」,走向明天的「讀懂告警」。
我們明天見!